# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: leon, xguo

import abc
import datetime
import logging

from typing import List, Optional, Union

import coin.flow.topic_map as topic_map
from coin.base.param_util import to_list
from coin.exchange.base.kr_rest.product import NativeProduct


class PrivateQueryerBase(metaclass=abc.ABCMeta):
  def __init__(self,
               queue,
               worker_id: int,
               product: Union[List[NativeProduct], NativeProduct],
               exchange,
               async_private_client,
               period=None,
               logger=None):
    self._logger = logger or logging.getLogger(__name__)
    self._product = to_list(product)
    self._period = period or datetime.timedelta(seconds=3)
    self._exchange = exchange
    self._async_private_client = async_private_client

    self._context = None
    self._publisher = None
    self._init_publisher(queue, worker_id)

  def __del__(self):
    self.stop()
    self._publisher.close()

  def _init_publisher(self, queue, worker_id):
    topic_id = topic_map.search_topic_id('%s_rest_private_*%s' %
                                         (self._exchange.lower(), worker_id))[0][1]
    self._publisher = queue.get_writer(topic_id=topic_id)

  @abc.abstractmethod
  def _init_context(self, ioloop):
    raise NotImplementedError()

  def start(self, ioloop, later_td: Optional[datetime.timedelta] = None):
    self._init_context(ioloop)

    if later_td is None:
      self._context.start()
    else:
      ioloop.add_timeout(later_td, self._context.start)

  def stop(self):
    if self._context is not None:
      self._context.stop()
      self._context = None
